//
//  XWXSqliteTable.m
//  XWXSqlite
//
//  Created by 许卫星 on 17/9/4.
//  Copyright © 2017年 wxxu. All rights reserved.
//

#import "XWXSqliteTable.h"
#import "XWXSqliteDataBase.h"
#import "XWXSqliteDataBasePool.h"
#import "XWXSqliteConfiguration.h"

static NSLock *dbClassLock;

@implementation XWXSqliteTable

+ (BOOL)executeSQL:(NSString *)sqlString withDBName:(NSString *)dbName error:(NSError **)error
{
    NSLog(@"sqlString:%@",sqlString);
    [[self dbLock] lock];
    //1.获取并打开数据库
    XWXSqliteDataBase *sqliteDB = [[XWXSqliteDataBasePool sharedInstance] databaseWithName:dbName];
    
    //2.执行sql
    BOOL result = sqlite3_exec(sqliteDB.database, sqlString.UTF8String, NULL, NULL, NULL);
    
    if (result != SQLITE_OK && error) {
        //错误信息
        const char *errorMsg = sqlite3_errmsg(sqliteDB.database);
        NSError *generatedError = [NSError errorWithDomain:kXWXSqliteErrorDomain code:XWXSqliteErrorCodeQueryStringError userInfo:@{NSLocalizedDescriptionKey:[NSString stringWithFormat:@"\n======================\nQuery Error: \n Origin Query is : %@\n Error Message is: %@\n======================\n", sqlString, [NSString stringWithCString:errorMsg encoding:NSUTF8StringEncoding]]}];
        *error = generatedError;
        NSLog(@"%@",generatedError.localizedDescription);
    }
    
    //关闭数据库
    [sqliteDB closeDB];
    [[self dbLock] unlock];
    
    return result;
}

+ (BOOL)executeSQLArray:(NSArray<NSString *> *)sqlStrings withDBName:(NSString *)dbName error:(NSError **)error
{
    //1.获取并打开数据库
    [[self dbLock] lock];
    XWXSqliteDataBase *sqliteDB = [[XWXSqliteDataBasePool sharedInstance] databaseWithName:dbName];
    //2.开启事物
    [sqliteDB beginTransaction];
    
    for (NSString *sqlString in sqlStrings) {
        NSLog(@"sqlString:%@",sqlString);
        //3.执行sql
        BOOL result = sqlite3_exec(sqliteDB.database, sqlString.UTF8String, NULL, NULL, NULL);
        
        if (result != SQLITE_OK && error) {
            //错误信息
            const char *errorMsg = sqlite3_errmsg(sqliteDB.database);
            NSError *generatedError = [NSError errorWithDomain:kXWXSqliteErrorDomain code:XWXSqliteErrorCodeQueryStringError userInfo:@{NSLocalizedDescriptionKey:[NSString stringWithFormat:@"\n======================\nQuery Error: \n Origin Query is : %@\n Error Message is: %@\n======================\n", sqlString, [NSString stringWithCString:errorMsg encoding:NSUTF8StringEncoding]]}];
            *error = generatedError;
            NSLog(@"%@",generatedError.localizedDescription);
            
            //.回滚事物
            [sqliteDB rollBackTransaction];
            [sqliteDB closeDB];
            [[self dbLock] unlock];
            return YES;
        }
    }
    
    //提交事物
    [sqliteDB commitTransaction];
    //关闭数据库
    [sqliteDB closeDB];
    [[self dbLock] unlock];
    return SQLITE_OK;
}


+ (NSArray *)fetchWithSQL:(NSString *)sqlString withDBName:(NSString *)dbName error:(NSError **)error
{
    NSLog(@"sqlString:%@",sqlString);
    [[self dbLock] lock];
    //1.获取打开数据库
    XWXSqliteDataBase *sqliteDB = [[XWXSqliteDataBasePool sharedInstance] databaseWithName:dbName];
    
    //2.预处理
    NSMutableArray *resultsArray = [[NSMutableArray alloc] init];
    sqlite3_stmt *ppStemt;
    BOOL result = sqlite3_prepare(sqliteDB.database, sqlString.UTF8String, -1, &ppStemt, NULL);
    if (result != SQLITE_OK && error) {
        //错误信息
        const char *errorMsg = sqlite3_errmsg(sqliteDB.database);
        NSError *generatedError = [NSError errorWithDomain:kXWXSqliteErrorDomain code:XWXSqliteErrorCodeQueryStringError userInfo:@{NSLocalizedDescriptionKey:[NSString stringWithFormat:@"\n======================\nQuery Error: \n Origin Query is : %@\n Error Message is: %@\n======================\n", sqlString, [NSString stringWithCString:errorMsg encoding:NSUTF8StringEncoding]]}];
        *error = generatedError;
        
        //关闭数据库
        [sqliteDB closeDB];
        [[self dbLock] unlock];
        return resultsArray;
    }
    
    //3.遍历查询结果
    while (sqlite3_step(ppStemt) == SQLITE_ROW) {
        
        NSMutableDictionary *resultDic = [[NSMutableDictionary alloc] init];
        [resultsArray addObject:resultDic];
        //1.获取列数
        NSInteger columnCount = sqlite3_column_count(ppStemt);
        //2.循环获取列信息
        for (int i = 0; i < columnCount; i++) {
            
            //3.获取列名称
            const char *name = sqlite3_column_name(ppStemt, i);
            NSString *columnName = [NSString stringWithUTF8String:name];
            if (columnName.length == 0) {
                continue;
            }
            //4.获取列类型
            int type = sqlite3_column_type(ppStemt, i);
            id value;
            
            //5.根据类型获取数据
            switch (type) {
                case SQLITE_INTEGER:{//整型
                    value = @(sqlite3_column_int(ppStemt, i));
                    break;
                }
                case SQLITE_FLOAT:{//浮点
                    value = @(sqlite3_column_double(ppStemt, i));
                    break;
                }
                case SQLITE_BLOB:{//二进制
                    value = CFBridgingRelease(sqlite3_column_blob(ppStemt, i));
                    break;
                }
                case SQLITE_NULL:{//空
                    value = @"";
                    break;
                }
                case SQLITE3_TEXT:{//文本
                    const char *valueC = (const char *)sqlite3_column_text(ppStemt, i);
                    value = [NSString stringWithUTF8String:valueC];
                    break;
                }
                    
                default:{
                    const char *valueC = (const char *)sqlite3_column_text(ppStemt, i);
                    value = [NSString stringWithUTF8String:valueC];
                }
                    break;
            }
            [resultDic setObject:value forKey:columnName];
        }
    }
    sqlite3_finalize(ppStemt);
    //关闭数据库
    [sqliteDB closeDB];
    [[self dbLock] unlock];
    
    return resultsArray;
}

+ (NSLock *)dbLock
{
    if (dbClassLock == nil) {
        dbClassLock = [[NSLock alloc] init];
    }
    return dbClassLock;
}
@end
